
jQuery.extend( {


    createUploadIframe: function ( id, uri ) {
        //create frame
        var frameId = 'jUploadFrame' + id;
        var iframeHtml = '<iframe id="' + frameId + '" name="' + frameId + '" style="position:absolute; top:-9999px; left:-9999px"';
        if ( window.ActiveXObject ) {
            if ( typeof uri == 'boolean' ) {
                iframeHtml += ' src="' + 'javascript:false' + '"';

            }
            else if ( typeof uri == 'string' ) {
                iframeHtml += ' src="' + uri + '"';

            }
        }
        iframeHtml += ' />';
        jQuery( iframeHtml ).appendTo( document.body );

        return jQuery( '#' + frameId ).get( 0 );
    },
    createUploadForm: function ( id, fileElementId ) {
        //create form	
        var formId = 'jUploadForm' + id;
        var fileId = 'jUploadFile' + id;
        var form = jQuery( '<form  action="" method="POST" name="' + formId + '" id="' + formId + '" enctype="multipart/form-data"></form>' );
        var oldElement = jQuery( '#' + fileElementId );
        var newElement = jQuery( oldElement ).clone();
        jQuery( oldElement ).attr( 'id', fileId );
        jQuery( oldElement ).before( newElement );
        jQuery( oldElement ).appendTo( form );
        //set attributes
        jQuery( form ).css( 'position', 'absolute' );
        jQuery( form ).css( 'top', '-1200px' );
        jQuery( form ).css( 'left', '-1200px' );
        jQuery( form ).appendTo( 'body' );
        return form;
    },

    ajaxFileUpload: function ( s ) {
        // TODO introduce global settings, allowing the client to modify them for all requests, not only timeout		
        s = jQuery.extend( {}, jQuery.ajaxSettings, s );
        var id = new Date().getTime()
        var form = jQuery.createUploadForm( id, s.fileElementId );
        var io = jQuery.createUploadIframe( id, s.secureuri );
        var frameId = 'jUploadFrame' + id;
        var formId = 'jUploadForm' + id;
        // Watch for a new set of requests
        if ( s.global && !jQuery.active++ ) {
            jQuery.event.trigger( "ajaxStart" );
        }
        var requestDone = false;
        // Create the request object
        var xml = {}
        if ( s.global )
            jQuery.event.trigger( "ajaxSend", [xml, s] );
        // Wait for a response to come back
        var uploadCallback = function ( isTimeout ) {
            var io = document.getElementById( frameId );
            try {
                if ( io.contentWindow ) {
                    xml.responseText = io.contentWindow.document.body ? io.contentWindow.document.body.innerHTML : null;
                    xml.responseXML = io.contentWindow.document.XMLDocument ? io.contentWindow.document.XMLDocument : io.contentWindow.document;

                } else if ( io.contentDocument ) {
                    xml.responseText = io.contentDocument.document.body ? io.contentDocument.document.body.innerHTML : null;
                    xml.responseXML = io.contentDocument.document.XMLDocument ? io.contentDocument.document.XMLDocument : io.contentDocument.document;
                }
            } catch ( e ) {
                jQuery.handleError( s, xml, null, e );
            }
            if ( xml || isTimeout == "timeout" ) {
                requestDone = true;
                var status;
                try {
                    status = isTimeout != "timeout" ? "success" : "error";
                    // Make sure that the request was successful or notmodified
                    if ( status != "error" ) {
                        // process the data (runs the xml through httpData regardless of callback)
                        var data = jQuery.uploadHttpData( xml, s.dataType );
                        // If a local callback was specified, fire it and pass it the data
                        if ( s.success )
                            s.success( data, status );

                        // Fire the global callback
                        if ( s.global )
                            jQuery.event.trigger( "ajaxSuccess", [xml, s] );
                    } else
                        jQuery.handleError( s, xml, status );
                } catch ( e ) {
                    status = "error";
                    jQuery.handleError( s, xml, status, e );
                }

                // The request was completed
                if ( s.global )
                    jQuery.event.trigger( "ajaxComplete", [xml, s] );

                // Handle the global AJAX counter
                if ( s.global && ! --jQuery.active )
                    jQuery.event.trigger( "ajaxStop" );

                // Process result
                if ( s.complete )
                    s.complete( xml, status );

                jQuery( io ).unbind()

                setTimeout( function () {
                    try {
                        jQuery( io ).remove();
                        jQuery( form ).remove();

                    } catch ( e ) {
                        jQuery.handleError( s, xml, null, e );
                    }

                }, 100 )

                xml = null

            }
        }
        // Timeout checker
        if ( s.timeout > 0 ) {
            setTimeout( function () {
                // Check to see if the request is still happening
                if ( !requestDone ) uploadCallback( "timeout" );
            }, s.timeout );
        }
        try {

            var form = jQuery( '#' + formId );
            jQuery( form ).attr( 'action', s.url );
            jQuery( form ).attr( 'method', 'POST' );
            jQuery( form ).attr( 'target', frameId );
            if ( form.encoding ) {
                jQuery( form ).attr( 'encoding', 'multipart/form-data' );
            }
            else {
                jQuery( form ).attr( 'enctype', 'multipart/form-data' );
            }
            jQuery( form ).submit();

        } catch ( e ) {
            jQuery.handleError( s, xml, null, e );
        }

        jQuery( '#' + frameId ).load( uploadCallback );
        return { abort: function () { } };

    },

    uploadHttpData: function ( r, type ) {
        var data = !type;
        data = type == "xml" || data ? r.responseXML : r.responseText;
        // If the type is "script", eval it in global context
        if ( type == "script" )
            jQuery.globalEval( data );
        // Get the JavaScript object, if JSON is used.
        if ( type == "json" )
            eval( "data = " + data );
        // evaluate scripts within html
        if ( type == "html" )
            jQuery( "<div>" ).html( data ).evalScripts();

        return data;
    }
} );


function upload( uploadUrl, uploadElementId, onSuccess, onCompleted, onError ) {
    $.ajaxFileUpload( {
        url: uploadUrl,
        secureuri: false,
        fileElementId: uploadElementId,
        dataType: 'json',
        success: function ( data, status ) {
            if ( onSuccess ) {
                onSuccess( data, status );
            }
        },
        error: function ( xhr, status, e ) {
            if ( onError ) {
                onError( data, status, e );
            }
        }
    } )
};
